# -*- coding=utf-8 -*-
from retrying import retry
from json.decoder import JSONDecodeError
from .app_config import AppConfig
from .http_client import HttpClient
from . import error


class ApiRequestor(HttpClient, AppConfig):

    @classmethod
    def call_request(cls, method, url, params):
        """
        执行请求
        :param method: 请求方式
        :param url: 请求地址
        :param params: 请求参数
        :return: 返回响应结果
        """
        config_info = AppConfig.get_config_info()
        if config_info["bad_gateway_match"]:
            @retry(
                stop_max_attempt_number=config_info["max_network_retries"] + 1,
                wait_fixed=config_info["network_retry_delay"] * 1000
            )
            def request_with_retry():
                return cls.__request_raw(method, url, params)

            return cls.__interpret_response(request_with_retry())
        else:
            return cls.__interpret_response(cls.__request_raw(method, url, params))

    @staticmethod
    def __request_raw(method, url, params):
        """
        处理请求信息
        :param method: 请求方式
        :param url: 请求地址
        :param params: 请求参数
        :return: 返回响应信息
        """
        if method == 'GET' or method == 'DELETE' or method == 'POST' or method == 'PUT':
            try:
                response = HttpClient.request(method, url, params)
            except Exception as e:
                raise error.RequestError(f"Invalid Request {e}")
            else:
                return response
        else:
            raise error.RequestError(f"Invalid request method {method}")

    @staticmethod
    def __interpret_response(response):
        """
        处理响应信息
        :param response: 响应
        :return: 返回响应结果
        """
        try:
            result = response.json()
        except JSONDecodeError as e:
            raise error.ResponseError(
                f"Invalid response body from API:{e} "
            )
        else:
            if result["code"] == 0 and result["msg"] == "SUCCESS":
                return result
            else:
                raise error.APIError(
                    f"Invalid response body from API:{result['msg']} "
                    f"(HTTP response code was {result['code']})"
                )
